#include "server.h"
#define DBG(X)\
{\
    perror(X);\
    exit(1);\
}
#define MAX_CLIENT 5

string server::result="";
server::server()
{
    memset(&server_addr, 0x0, sizeof(server_addr));
    memset(&client_addr, 0x0, sizeof(client_addr));
    int addr_len = sizeof(server_addr);
//    char buf[1024];
    server_fd = socket(AF_INET, SOCK_STREAM, 0);

    server_addr.sin_family = AF_INET;

    server::port = 4500;
    server::result="";

    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(server_fd, (struct sockaddr*)&server_addr,
             sizeof(server_addr))<0)
    {
        DBG("bind");
    }

    if ((listen(server_fd, MAX_CLIENT))<0)
    {
        DBG("listen");
    }

    while (1)
    {
        pthread_t thread;
        client_fd = accept(server_fd, (struct sockaddr*)&client_addr,
                           (socklen_t*)&addr_len);
        if (client_fd < 0)
        {
            perror("accept");
            continue;
        }

        pthread_attr_t thread_attr;
        pthread_attr_init(&thread_attr);
        if (pthread_attr_setdetachstate(&thread_attr,
                                        PTHREAD_CREATE_DETACHED)<0)
        {
            DBG("thread set detachestate");
        }
//        vector args;
//        string hash("")
//        args.push_back(client_fd);
//        args.push_back(hash);
//        void* (server::*tmp_func)(void*);
//        tmp_func = &server::accept_client;
        pthread_create(&thread, &thread_attr, accept_client, &client_fd);
    }
    close(server_fd);
}

//function pointer can not be surrounded by parenthesis
//really weired, anyone knows?

void* server::md5_thread (void* arg)
{
    string hash((char*)arg);
    fstream fin("1.txt", ios::in);

    while(fin)
    {
        getline(fin, hash);
        md5 *tmp = new md5(hash);
        tmp->md5_init();
        tmp->md5_calc();
        if (hash.compare(tmp->md5_get_hash())==0)
        {
            result=tmp->md5_get_hash();
            return (void*)0x1;
        }
        delete tmp;
    }
    return NULL;
}

void* server::accept_client(void* args)
{
    char buf[1024]="";
    int client_fd = *((int*)(args));
rec:send(client_fd, "md5:>", 6, 0);
    int len=recv(client_fd, buf, sizeof(buf), 0);
    if (len != 34)
    {
        send(client_fd, "invalid input!", 15, 0);
        goto rec;
    }
    buf[32]='\0';
//    string user_hash(buf);
    pthread_t md5_thread1,md5_thread2;

    pthread_create(&md5_thread1, 0, md5_thread, buf);
    pthread_create(&md5_thread2, 0, md5_thread, buf);

    void* res=NULL;
    pthread_join(md5_thread1, &res);

    //returns 0 if not found
    if ((*(int*)res)==NULL)
    {
        pthread_join(md5_thread2, &res);
        if ((*(int*)res)==NULL)
        {
            send(client_fd, "NOT FOUND!", 11, 0);
        }
        else
        {
            send(client_fd, result.c_str(), strlen(result.c_str()), 0);
        }
    }
    close(client_fd);
    return NULL;
}

void* server::pthread_accept_client(void* args)
{
    return NULL;
}

void* server::pthread_md5_thread(void* args)
{
    return NULL;
}


